package tutor;

import static org.lwjgl.opengl.GL11.GL_SCISSOR_TEST;
import static org.lwjgl.opengl.GL11.glClipPlane;
import static org.lwjgl.opengl.GL11.glDisable;
import static org.lwjgl.opengl.GL11.glEnable;

import java.nio.DoubleBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

public class Game {
	private final int DEFAULT_FPS = 60;
	
	/* confs for home below */
	
	protected final int WIDTH = 800;
	protected final int HEIGHT = 600;
	protected final boolean IS_FULLSCREEN = false;
	
	/* fullscreen, fullHD */
//	protected final int WIDTH = 1920;
//	protected final int HEIGHT = 1080;
//	protected final boolean IS_FULLSCREEN = true;
	
	private static Game instance;

	public Game() {
		try {
			instance = this; // Set the static reference

			Display.setDisplayMode(new DisplayMode(250, 250));/*--!!! for work ONLY !!!--*/
			
			Display.create();
//			setDisplayMode(WIDTH, HEIGHT, IS_FULLSCREEN); /*-!!! for home only !!!-*/
			Display.setResizable(true);

			gameLoop();
			
		} catch (LWJGLException e) {
			e.printStackTrace();
			System.exit(-1);
		}
	}

	public void init() {
	}

	public void update(long elapsedTime) {
	}

	public void render() {
	}

	public void resized() {
	}

	public void dispose() {
	}
	
	public static long getCurrentTime() {
		return Sys.getTime() * 1000 / Sys.getTimerResolution();
	}

	private void gameLoop() {
		long lastFrame = getCurrentTime();
		long thisFrame = getCurrentTime();

		init();

		GL11.glScissor(50, 50, 150, 150);
		
		DoubleBuffer eqn1 = BufferUtils.createDoubleBuffer(8).put(new double[] {-1, 0, 0, 100});
		eqn1.flip();
		GL11.glClipPlane(GL11.GL_CLIP_PLANE0, eqn1);
		GL11.glEnable(GL11.GL_CLIP_PLANE0);
		
		while (!Display.isCloseRequested()) {
			thisFrame = getCurrentTime();
			update(thisFrame - lastFrame);
			render();

			lastFrame = thisFrame;
			Display.update();

			// Check the resize property
			if (Display.wasResized()) {
				resized();
			}

			Display.sync(DEFAULT_FPS);
		}

		end();
	}

	public static void end() {
		instance.dispose();
		Display.destroy();
		System.exit(0);
	}

	/**
	 * Sets a DisplayMode after selecting for a better one.
	 * @return True if switching is successful.
	 */
	public static boolean setDisplayMode(int width, int height, boolean fullscreen) {
		if ((Display.getDisplayMode().getWidth() == width)
				&& (Display.getDisplayMode().getHeight() == height)
				&& (Display.isFullscreen() == fullscreen)) {
			return true; // requested mode is already set
		}

		try {
			DisplayMode targetDisplayMode = null;
			
			if (fullscreen) {
				DisplayMode[] modes = Display.getAvailableDisplayModes();
				int freq = 0;
				for (DisplayMode current : modes) {
					if ((current.getWidth() == width) && (current.getHeight() == height)) {
						if ((targetDisplayMode == null) || (current.getFrequency() >= freq)) {
							if ((targetDisplayMode == null) || (current.getBitsPerPixel() > targetDisplayMode.getBitsPerPixel())) {
								targetDisplayMode = current;
								freq = targetDisplayMode.getFrequency();
							}
						}
						if ((current.getBitsPerPixel() == Display.getDesktopDisplayMode().getBitsPerPixel())
								&& (current.getFrequency() == Display.getDesktopDisplayMode().getFrequency())) {
							targetDisplayMode = current;
							break;
						}
					}
				}
			} else {
				targetDisplayMode = new DisplayMode(width, height);
			}
			
			if (targetDisplayMode == null) {
				System.out.println("Failed to find value mode: " + width + "x" + height + " fs=" + fullscreen);
				return false;
			}

			Display.setDisplayMode(targetDisplayMode);
			Display.setFullscreen(fullscreen);
			System.out.println("Selected DisplayMode: " + targetDisplayMode.toString());
			instance.resized();
			return true;
			
		} catch (LWJGLException e) {
			System.out.println("Unable to setup mode " + width + "x" + height + " fullscreen=" + fullscreen + e);
		}
		return false;
	}

}
